package cn.chint.util;

import com.google.common.net.UrlEscapers;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;

import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class BeanUtil {

    /**
     * 字符串中中文的做url重写
     * 一般用户url重写
     *
     * @param string
     * @return
     */
    public static String charEncode(String string) {
        if (!BeanUtil.isEmpty(string)) {
            Pattern p = Pattern.compile("[\\u4e00-\\u9fa5]");
            Matcher m = p.matcher(string);
            if (m.find()) {
                return UrlEscapers.urlFragmentEscaper().escape(string);
            }
        }
        return string;
    }

    /**
     * 将一个集合的数据复制到给定的类型的集合并返回
     *
     * @param src
     * @param target
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> List<T> copyPropertiesToListIgnoreNull(List src, Class<T> target) throws Exception {
        if (isEmpty(src)) return null;
        List<T> list = new ArrayList();
        for (Object o : src) {
            T t = target.newInstance();
            copyPropertiesIgnoreNull(o, t);
            list.add(t);
        }
        return list;
    }

    /**
     * 拷贝一个对象的属性到另一个有相同属性的对象
     *
     * @param src
     * @param target
     * @param <T>
     * @return
     * @throws Exception
     */
    public static <T> T copyPropertiesIgnoreNull(Object src, Class<T> target) throws Exception {
        if (isEmpty(src)) return null;
        T t = target.newInstance();
        copyPropertiesIgnoreNull(src, t);
        return t;
    }

    /**
     * 判断对象是否是空
     *
     * @param obj
     * @return
     */
    public static boolean isEmpty(Object obj) {
        return obj == null ? true :
                obj instanceof Collection ? ((Collection) obj).isEmpty() :
                        obj instanceof Object[] ? ((Object[]) obj).length == 0 :
                                obj instanceof String ? ((String) obj).trim().equals("") :
                                        obj instanceof Map ? ((Map) obj).isEmpty() : false;
    }

    private static String[] getNullPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }


    private static String[] getEmptyPropertyNames(Object source) {
        final BeanWrapper src = new BeanWrapperImpl(source);
        java.beans.PropertyDescriptor[] pds = src.getPropertyDescriptors();

        Set<String> emptyNames = new HashSet<String>();
        for (java.beans.PropertyDescriptor pd : pds) {
            Object srcValue = src.getPropertyValue(pd.getName());
            if (srcValue == null || "".equals(srcValue)) emptyNames.add(pd.getName());
        }
        String[] result = new String[emptyNames.size()];
        return emptyNames.toArray(result);
    }

    /**
     * 拷贝对象相同属性不复制为null字段
     *
     * @param src
     * @param target
     */
    public static void copyPropertiesIgnoreNull(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getNullPropertyNames(src));
    }

    /**
     * 将对象转换成map，对象的value一定要是可转换为string的属性
     *
     * @param object
     * @return
     */
    public static Map<String, String> beanToMapValueString(Object object) {
        if (isEmpty(object)) return null;
        Map<String, Object> map = cn.hutool.core.bean.BeanUtil.beanToMap(object);
        Map<String, String> orderMap = new HashMap();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            orderMap.put(entry.getKey(), entry.getValue() + "");
        }
        return orderMap;
    }

    public static void copyPropertiesIgnoreEmpty(Object src, Object target) {
        BeanUtils.copyProperties(src, target, getEmptyPropertyNames(src));
    }

}
